package star.planets.meshview;

import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;


import javax.media.j3d.Appearance;
import javax.media.j3d.Geometry;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Material;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TriangleFanArray;
import javax.vecmath.Color3f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Point3f;

import star.crust.cartspace.framework.CrtBody;
import star.crust.cartspace.framework.CrtMeshPrimitive;
import star.crust.cartspace.framework.CrtMeshVertex;


public class J3DBody implements Observer {
	private TransformGroup rootTG = null;
	private CrtBody body = null;

	public TransformGroup getRoot() {
		return rootTG;
	}
	public J3DBody(CrtBody body) {
		this.body = body;
		body.addObserver(this);
		
		// Create the TransformGroup node and initialize it to the
		// body home position. Enable the TRANSFORM_WRITE capability so that
		// our behavior code can modify it at run time. 
		Matrix4f matrix = body.getAbsolutePosition().matrix;
		Transform3D bt = new Transform3D(matrix);
		rootTG = new TransformGroup(bt);
		rootTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		rootTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		rootTG.setCapability(TransformGroup.ENABLE_PICK_REPORTING);

		// create the TriangleFanArray with the body mesh
		if(body.getGeometry() == null)
			return;
		Iterator<CrtMeshPrimitive> meshIterator = body.getGeometry().iterator();
		int count = 1;
		CrtMeshPrimitive tm = null;
		Geometry geom = null;
		while(meshIterator.hasNext()) {
			tm = meshIterator.next();
//			System.out.println("^^^^^^^^^^^^^ J3DBody type = " + tm.getType());
			count++;
			if(tm.getType().equals("trifans") || tm.getType().equals("triangles"))
				geom = getTriangleFanArray(tm);

			if(geom == null)
				continue;
			Material m = new Material() ;
			Appearance appearance = new Appearance();
			appearance.setMaterial(m) ;
			m.setLightingEnable(true) ;

			Shape3D shape = new Shape3D(geom,appearance);
			shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
			shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
			shape.setCapability(Shape3D.ENABLE_PICK_REPORTING);
			rootTG.addChild(shape);
		}	
	}
		
	
	public TriangleFanArray getTriangleFanArray(CrtMeshPrimitive mp) {
		TriangleFanArray tfa = null;
		Color3f colors[] = new Color3f[3];
		colors[0] = new Color3f(1.0f, 0.0f, 0.0f);
		colors[1] = new Color3f(1.0f, 1.0f, 0.0f);
		colors[2] = new Color3f(0.0f, 1.0f, 1.0f);

		int size = mp.size();
		Point3f vertices[] =  new Point3f[size];
		CrtMeshVertex vertex = null;
		for(int i=0; i < size; i++) {
			vertex = mp.getVertex(i);
			vertices[i] = new Point3f(vertex.position().x, vertex.position().y, vertex.position().z);
		}
		int[] sVertCnt = { size };
		tfa = new TriangleFanArray(size, GeometryArray.COORDINATES | GeometryArray.COLOR_3, sVertCnt);
		tfa.setCoordinates(0, vertices);
		tfa.setColors(0, colors);

		return tfa;
	}		
	
	public void update(Observable arg0, Object arg1) {
		String event = (String) arg1;
		if(event.equals("POSITION_CHANGED")) {
			Matrix4f matrix = body.getAbsolutePosition().matrix;
			Transform3D bt = new Transform3D(matrix);
			rootTG.setTransform(bt);
		}
	}
}
